

class Compiler {
  constructor(vm) {
    // console.log(vm.$el);
    this.el = vm.$el;
    this.vm = vm;
    this.compile(this.el);
  }
  compile(el) {
    // console.log(el.childNodes);
    // console.log(Array.isArray(el.childNodes));

    Array.from(el.childNodes).forEach(node => {
      // console.log("node:", node);

      if (this.isTextNode(node)) {
        // 文本节点
        this.compileText(node)
      } else if (this.isElementNode(node)) {
        // console.log(node);
        this.compileElement(node);
      }
      if (node.childNodes && node.childNodes.length > 0) {
        // 有孩子
        // console.log(node + "节点有孩子");
        this.compile(node)
      }
    })
  }
  // 编译元素节点
  compileElement(node) {
    Array.from(node.attributes).forEach(attr => {
      let attrName = attr.name;
      if (this.isDirective(attrName)) {
        attrName = attrName.substr(2)
        // console.log(attrName);
        let key = attr.value;
        // node是节点  key是数据的值  attrName是属性名
        // v-text = "msg"   key是msg  attrName是text
        this.update(node, key, attrName)
      }
    })
  }
  update(node, key, attrName) {
    // 在模板中可能有很多的指令
    // 编译不同的指令，需要写不同的方法
    // 编译text指令   调用textUpdater
    // 编译model指令   调用modelUpdater
    let updateFn = this[attrName + "Updater"]
    updateFn && updateFn(node, this.vm[key])
  }
  // 处理v-text指令
  textUpdater(node, value) {
    node.textContent = value;
  }
  // 处理v-model指令
  modelUpdater(node, value) {
    node.value = value;
  }
  // 编译文本节点
  compileText(node) {
    let reg = /\{\{(.+)\}\}/;
    let value = node.textContent;
    if (reg.test(value)) {
      let key = RegExp.$1.trim();
      node.textContent = value.replace(reg, this.vm[key])
    }
  }
  // 判断一个节点是否是文本节节点
  isTextNode(node) {
    return node.nodeType === 3;
  }
  // 判断一个节点是否是元素节点
  isElementNode(node) {
    return node.nodeType === 1;
  }
  // 判断一个属性节点是否是一个指令
  isDirective(attrName) {
    return attrName.startsWith("v-")
  }
}